package gt

import (
	"gitee.com/dark.H/gs"
)

type PanelMenu struct {
	*PanelHandler
	Selected gs.Str
	IfFocus  bool

	PosX  int
	Names gs.List[gs.Str]
	items gs.Dict[func() gs.List[gs.Str]]
	calls gs.Dict[func()]
}

func NewPanelMenu() *PanelMenu {
	p := &PanelMenu{
		PanelHandler: NewPanelHandler(),
		items:        make(gs.Dict[func() gs.List[gs.Str]]),
		calls:        make(gs.Dict[func()]),
	}
	r, c := gs.GetWindowsSize()
	p.SetBorder(false).SetBar(false)
	p.SetSizeHeight(1).SetLoc(1, r).SetSizeWidth(c)
	p.SetDrawFunc(p.draw)
	p.key()
	p.SetMouse(true)
	return p
}

func (pm *PanelMenu) MoveRight() *PanelMenu {
	// names := pm.Items.Keys().Sort(gs.SortLen)
	names := pm.Names
	ev := pm.Width / names.Count()
	ix := -1
	names.Every(func(no int, i gs.Str) {
		if pm.Selected == i {
			ix = no
		}
	})
	if pm.Selected == "" {
		pm.Selected = names[0]
		pm.PosX = 1
		return pm
	}
	if ix == -1 {
		return pm
	}
	ix += 1
	ix = ix % names.Count()
	if ix == 0 {
		pm.PosX = 0
		// return pm
	}
	pm.Selected = names[ix]
	cc := pm.Selected.Len()
	if cc > ev {
		cc = ev
	}
	pm.PosX += cc
	return pm
}

func (pm *PanelMenu) MoveLeft() *PanelMenu {
	// names := pm.Items.Keys().Sort(gs.SortLen)

	names := pm.Names
	// ev := pm.Width / names.Count()
	ix := -1
	names.Every(func(no int, i gs.Str) {
		if pm.Selected == i {
			ix = no
		}
	})

	if pm.Selected == "" {
		pm.Selected = names[0]
		// pm.PosX = 1
		return pm
	}
	if ix == -1 {
		return pm
	}

	ix -= 1
	ix = ix % names.Count()
	pm.Selected = names[ix]
	if ix == names.Count()-1 {

		// pm.PosX = pm.Width
		return pm
	}
	return pm
}

func (pm *PanelMenu) AddItem(name string, c func() gs.List[gs.Str]) *PanelMenu {
	pm.items[name] = c
	if !pm.Names.In(gs.Str(name)) {
		pm.Names = pm.Names.Add(gs.Str(name))
	}
	return pm
}

func (pm *PanelMenu) draw() {
	ic := pm.items.Len()
	width := pm.Width / ic
	con := gs.Str("")
	names := pm.Names
	for _, name := range names {
		n := gs.Str(name)

		if n.Len() > width {
			n = n[:width]
		}
		n = " " + n + " "
		if name == pm.Selected {
			pm.PosX = con.Len()
			n = n.Color("g").ANSISelected()
		}
		if con != "" {
			con += gs.Str("|")
		}
		con += n
	}
	pm.Write(con)
}

func (pm *PanelMenu) key() {
	pm.OnkeyEnter(func(parentPanel *PanelHandler) bool {
		pm.ToggleSelected()
		return false
	}).OnkeyCh('l', func(parentPanel *PanelHandler) bool {
		pm.MoveRight()
		return false
	}).OnkeyCh('h', func(parentPanel *PanelHandler) bool {
		pm.MoveLeft()
		return false
	}).OnClick(func(x, y int, panel *PanelHandler) bool {
		// gs.Str("click : %d").F(y).ToFile("/tmp/click.txt")
		if y == panel.loc.Y-1 {
			// panel.LogInfo("/tmp/click.txt")
			found := false
			st := 0
			pm.Names.Every(func(no int, i gs.Str) {
				if !found {

					// gs.Str("click: x: %d now offset : %d .  len: %d\n").F(x, st, i.Len(true)).ToFile("/tmp/click.txt")

					if x > st && x < st+i.Len(true)+3 {
						pm.Selected = i
						// pm.selectedNum = no
					}
					st += i.Len(true) + 3

				}

			})

		} else {
			// panel.LogInfo("/tmp/noclick.txt")
		}
		return false
	})

}

func (pm *PanelMenu) OnItemToggle(item gs.Str, c func()) {
	pm.calls[item.Str()] = c
}

func (pm *PanelMenu) ToggleSelected() {
	if call, ok := pm.items[pm.Selected.Str()]; ok {
		if subitems := call(); subitems.Count() > 0 {
			_, y := pm.Loc()
			pm.Switch(func(parentPanel *PanelHandler) bool {
				subitems := NewListItemsPanel(subitems)
				subitems.OnkeyEnter(func(parentPanel *PanelHandler) bool {
					if call, ok := pm.calls[subitems.Selected().Str()]; ok {
						call()
					}
					return true
				})
				subitems.SetBar(false).SetSizeWidth(30).SetLoc(pm.PosX, y, true)
				subitems.Focus()
				subitems.Clear()
				return true
			})

		}
	}
}
